#include "singleMember.h"
#include "common.h"
#include "global.h"

#include <iostream>
using namespace std;

singleMember::singleMember()
:m_name("")
{
}

singleMember::singleMember(const std::string &name, u_long net_addr)
:m_name(name),
 m_net_addr(net_addr)
{
}

singleMember::~singleMember()
{
	removeAll(m_my_xigama);
	removeAll(m_my_pubH);
	removeAll(m_my_pubR);
	removeAll(m_my_pubA);
	if (localname.compare(m_name) != 0)
		closesocket(m_socket);
}

void singleMember::setSocket(SOCKET thesock)
{
	m_socket = thesock;
}

void singleMember::setNetAddr(u_long net_addr)
{
	m_net_addr = net_addr;
}

void singleMember::setName(const std::string &name)
{
	m_name = name;
}

int singleMember::setXigama(const std::string &groupname, c_asgka_element content)
{
	int retval;
	asgka_element temp;
	asgka_malloc(temp);
	retval = strcpy_s(temp, LENGTH, content);
	if (isPairExist(m_my_xigama, groupname))
		m_my_xigama[groupname] = temp;
	return retval;
}

int singleMember::setpubH(const std::string &groupname, c_asgka_element content)
{
	cout << "Now set the pubH for " << groupname << endl;
	int retval;
	asgka_element temp;
	asgka_malloc(temp);
	retval = strcpy_s(temp, LENGTH, content);
	if (isPairExist(m_my_pubH, groupname))
		m_my_pubH[groupname] = temp;
	return retval;
}

int singleMember::setpubR(const std::string &groupname, c_asgka_element content)
{
	int retval;
	asgka_element temp;
	asgka_malloc(temp);
	retval = strcpy_s(temp, LENGTH, content);
	if (isPairExist(m_my_pubR, groupname))
		m_my_pubR[groupname] = temp;
	return retval;
}

int singleMember::setpubA(const std::string &groupname, c_asgka_element content)
{
	int retval;
	asgka_element temp;
	asgka_malloc(temp);
	retval = strcpy_s(temp, LENGTH, content);
	if (isPairExist(m_my_pubA, groupname))
		m_my_pubA[groupname] = temp;
	return retval;
}

long singleMember::getMemberID() const
{
	return m_id;
}

char * FAR singleMember::getMemberIP() const
{
	in_addr addr;
	addr.S_un.S_addr = m_net_addr;
	return inet_ntoa(addr);
}

u_long singleMember::getNetAddr() const
{
	return m_net_addr;
}

SOCKET singleMember::getSock() const
{
	return m_socket;
}

std::string singleMember::getMemberName() const
{
	return m_name;
}

asgka_element singleMember::getMemberXigama(const std::string &groupname) const
{
	return getValueOfPair(m_my_xigama, groupname);
}

asgka_element singleMember::getMemberpubH(const std::string &groupname) const
{
	return getValueOfPair(m_my_pubH, groupname);
}

asgka_element singleMember::getMemberpubR(const std::string &groupname) const
{
	return getValueOfPair(m_my_pubR, groupname);
}

asgka_element singleMember::getMemberpubA(const std::string &groupname) const
{
	return getValueOfPair(m_my_pubA, groupname);
}

bool singleMember::isAlone() const
{
	int size = 0;
	size += m_my_xigama.size();
	size += m_my_pubH.size();
	size += m_my_pubR.size();
	size += m_my_pubA.size();
	return (size == 0);
}

bool singleMember::isXigamaOK(const std::string &groupname) const
{
	return !(getValueOfPair(m_my_xigama, groupname) == NULL);
}

bool singleMember::isPubHOK(const std::string &groupname) const
{
	return !(getValueOfPair(m_my_pubH, groupname) == NULL);
}

bool singleMember::isPubROK(const std::string &groupname) const
{
	return !(getValueOfPair(m_my_pubR, groupname)  == NULL);
}

bool singleMember::isPubAOK(const std::string &groupname) const
{
	return !(getValueOfPair(m_my_pubA, groupname)  == NULL);
}

void singleMember::joinedAGroup(const std::string &groupname)
{
	addPairToMap(m_my_xigama, groupname, NULL);
	addPairToMap(m_my_pubH, groupname, NULL);
	addPairToMap(m_my_pubR, groupname, NULL);
	addPairToMap(m_my_pubA, groupname, NULL);
}

void singleMember::leftAGroup(const std::string &groupname)
{
	removeOneFromMap(m_my_xigama, groupname);
	removeOneFromMap(m_my_pubH, groupname);
	removeOneFromMap(m_my_pubR, groupname);
	removeOneFromMap(m_my_pubA, groupname);
}

void singleMember::addPairToMap(std::map<std::string,asgka_element> &themap, 
								const std::string &key, asgka_element value)
{
	if (!isPairExist(themap, key))
		themap.insert(stoevalType(key, value));
}

void singleMember::removeOneFromMap(std::map<std::string,asgka_element> &themap,
									const std::string &index)
{
	std::map<std::string, asgka_element>::iterator it = themap.find(index);
	if (it != themap.end())
	{
		if (it->second != NULL)
			asgka_free(it->second);
		themap.erase(it);
	}
}

void singleMember::removeAll(std::map<std::string,asgka_element> &themap)
{
	std::map<std::string, asgka_element>::iterator it = themap.begin();
	while (it != themap.end())
	{
		if (it->second != NULL)
			asgka_free(it->second);
		themap.erase(it++);
	}
}

asgka_element singleMember::getValueOfPair(const std::map<std::string, asgka_element> &themap, 
										   const std::string &index) const
{
	std::map<std::string, asgka_element>::const_iterator it = themap.find(index);
	if (it != themap.end())
		return it->second;
	else
		return NULL;
}

bool singleMember::isPairExist(const std::map<std::string, asgka_element> &themap,
							   const std::string &index) const
{
	std::map<std::string, asgka_element>::const_iterator it = themap.find(index);
	return (it != themap.end());
}
